﻿using System;
using System.IO.Ports;
using BaseDll;
using System.Windows.Forms;
using Modbus;
using Modbus.Device;
using System.IO;
using System.Threading.Tasks;
using System.Threading;

namespace MotionIoLib
{
    public class IoCtrl_HY3 : IoCtrl
    {
        [NonSerialized]
        private static SerialPort _serialPort = null;
        [NonSerialized]
        private readonly object _disposingLock = new object();
        [NonSerialized]
        private static readonly object _syncRoot = new object();
        [NonSerialized]
        private IModbusSerialMaster _master;

        bool[] bOuts = new bool[64];

        private int _axexCount = 2;

        private bool[][] DIs;

        private bool[][] DOs;


        static AnicetSerialPortParam anicetParam = new AnicetSerialPortParam();

        public IoCtrl_HY3(int nIndex, ulong nCardNo)
            : base(nIndex, nCardNo)
        {
            m_strCardName = $"IoCtrl_HY3_{nCardNo}";
        }
        object ReadParam()
        {
            object obj = null;
            try
            {
                var path = Path.GetFullPath("..") + "//_Updata//" + $"\\Config\\{m_strCardName}.xml";
                obj = AccessXmlSerializer.XmlToObject(path, anicetParam.GetType());
                anicetParam = (AnicetSerialPortParam)obj;
            }
            catch
            {
                obj = null;
            }
            if (obj == null)
            {
                MessageBox.Show("Anicet IO 串口 数据读取出错", "Err", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            return obj;
        }
        void Save()
        {
            string strPath = Path.GetFullPath("..") + "//_Updata//" + $"\\Config\\{m_strCardName}.xml";
            AccessXmlSerializer.ObjectToXml(strPath, anicetParam);
        }

        public override bool Init()
        {
            // m_bOpen = m_comLink ==null ? false : m_comLink.IsOpen();
            if (ReadParam() == null)
            {
                Save();
            }
            try
            {
                if (_serialPort == null)
                    _serialPort = new SerialPort("COM" + anicetParam.m_nComNo.ToString())
                    {
                        BaudRate = anicetParam.m_nBaudRate,
                        DataBits = anicetParam.m_nDataBit,
                        Parity = (Parity)Enum.Parse(typeof(Parity), anicetParam.m_strPartiy),
                        StopBits = (StopBits)Enum.Parse(typeof(StopBits), anicetParam.m_strStopBit)
                    };
                // if (_serialPort.IsOpen)
                //     _serialPort.Close();
                _serialPort.ReadTimeout = 300;
                _serialPort.WriteTimeout = 300;
                if (!_serialPort.IsOpen)
                    _serialPort.Open();
                m_bOpen = _serialPort.IsOpen;
                _master = ModbusSerialMaster.CreateRtu(_serialPort);
                m_bOpen = true;

                //hlk - 2022 - 10 - 15
                DIs = new bool[_axexCount][];
                DOs = new bool[_axexCount][];
                for (int i = 0; i < _axexCount; i++)
                {
                    DIs[i] = new bool[16];
                    DOs[i] = new bool[16];
                }
                new Task(RefreshIO).Start();
            }
            catch (Exception)
            {
                m_bOpen = false;
                MessageBox.Show(string.Format("{0} 号卡{1} 打开失败 请检查配置", m_nCardNo, m_strCardName), "Err", MessageBoxButtons.OK, MessageBoxIcon.Error);
                // throw new Exception("IO控制器串口初始化失败," + ex.Message, ex);
            }
            return m_bOpen;
        }

        private void RefreshIO()
        {
            while (true)
            {
                try
                {
                    Thread.Sleep(10);
                    for (int i = 0; i < _axexCount; i++)
                    {
                        _master.WriteMultipleCoils((byte)(i + 1), 80, DOs[i]);
                        DIs[i] = _master.ReadCoils((byte)(i + 1), 16, 16);
                    }
                }
                catch { }
            }
        }
        /// <summary>
        ///释放IO卡 
        /// </summary>
        public override void DeInit()
        {
            if (_serialPort != null && _serialPort.IsOpen)
            {
                _serialPort.Close();
                _master.Dispose();
            }


        }

        /// <summary>
        ///获取卡所有的输入信号 
        /// </summary>
        /// <param name="nData"></param>
        /// <returns></returns>
        public override bool ReadIOIn(ref int nData)
        {
            return true;
        }

        /// <summary>
        ///获取卡所有的输出信号 
        /// </summary>
        /// <param name="nData"></param>
        /// <returns></returns>
        public override bool ReadIOOut(ref int nData)
        {

            return true;
        }

        /// <summary>
        ///按位获取输入信号 
        /// </summary>
        /// <param name="nIndex"></param>
        /// <returns></returns>
        public override bool ReadIoInBit(int nIndex)
        {
            //Thread.Sleep(50);
            if (!m_bOpen)
                return false;
            byte slaveAddress = (byte)(nIndex / 16 + 1);
            ushort coilAddress = (ushort)(nIndex % 16 + 16);
            bool brtn = false;
            try
            {
                lock (_syncRoot)
                {
                    brtn = DIs[nIndex / 16][nIndex % 16];
                }
                return brtn;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        ///按位获取输出信号 
        /// </summary>
        /// <param name="nIndex"></param>
        /// <returns></returns>
        public override bool ReadIoOutBit(int nIndex)
        {
            return DOs[nIndex / 16][nIndex % 16];
        }


        /// <summary>
        /// 按位输出信号 
        /// </summary>
        /// <param name="nIndex"></param>
        /// <param name="bBit"></param>
        /// <returns></returns>
        public override bool WriteIoBit(int nIndex, bool bBit)
        {
            if (!m_bOpen)
                return false;
            int nIoIndex = nIndex & 0xff;
            // Motion.mAcm_AxDoSetBit(m_Axishand[nAxisNo], (ushort)nIoIndex, byteWrite);
            byte slaveAddress = (byte)(nIndex / 16 + 1);
            ushort coilAddress = (ushort)(nIoIndex % 16 + 80);
            try
            {

                lock (_syncRoot)
                {
                    DOs[nIndex / 16][nIndex % 16] = bBit;
                }

                return true;
            }
            catch (Exception ex)
            {
                _master = ModbusSerialMaster.CreateRtu(_serialPort);
                return false;
            }
        }
        public override bool WriteIo(int nData)
        {
            return true;
        }

        public override bool InStopEnable(int nIndex)
        {
            return true;
        }
        public override bool InStopDisenable(int nIndex)
        {
            return true;
        }
    }
}